<template>
  <div class="exercise-container">
    <!-- 左侧知识点目录树 -->
    <div class="knowledge-tree">
      <div class="tree-header">
        <span class="title">知识点目录</span>
      </div>
      <div class="search-box">
        <el-input
          v-model="searchQuery"
          placeholder="搜索知识点"
          prefix-icon="el-icon-search"
          clearable
          @clear="handleSearchClear"
          @input="handleSearch">
        </el-input>
      </div>
      <el-tree
        ref="tree"
        :data="filteredTreeData"
        :props="defaultProps"
        @node-click="handleTreeNodeClick"
        :highlight-current="true"
        :expand-on-click-node="false"
        :filter-node-method="filterNode">
      </el-tree>
    </div>

    <!-- 图谱工具栏 -->
    <div class="toolbar">
      <el-button-group>
        <el-button size="small" @click="resetView">重置视图</el-button>
      </el-button-group>
    </div>

    <!-- 图谱区域 -->
    <div ref="chart" class="chart-container" @click="handleChartClick"></div>

    <!-- 详情面板 -->
    <div class="detail-panel" :class="{ 'show': drawerVisible, 'expanded': isExpanded }">
      <div class="detail-header">
        <div class="header-left">
          <span v-if="!isExpanded" class="expand-btn" @click="handleExpand">展开</span>
          <span v-else class="expand-btn" @click="handleCollapse">收起</span>
        </div>
        <div class="header-right">
          <span class="close-btn" @click="handleClose">×</span>
        </div>
      </div>
      <div class="detail-body" v-loading="loading">
        <div v-if="selectedNode" class="detail-content">
          <!-- 习题详情 -->
          <template v-if="selectedNode.type === 'exercise'">
            <div class="info-item">
              <span class="label">习题名称：</span>
              <span class="value">{{ selectedNode.name }}</span>
            </div>
            <div class="info-item">
              <span class="label">习题描述：</span>
              <div class="value description">{{ selectedNode.description }}</div>
            </div>
            <div class="info-item">
              <span class="label">所属知识点：</span>
              <div class="value tags">
                <span v-for="(point, index) in selectedNode.knowledgePoints" 
                      :key="index" 
                      class="tag knowledge-tag clickable"
                      @click="jumpToKnowledge(point)">
                  {{ point }}
                </span>
              </div>
            </div>
            <div class="info-item">
              <span class="label">前序知识点：</span>
              <div class="value tags">
                <span v-for="(point, index) in selectedNode.prerequisites" 
                      :key="index" 
                      class="tag prerequisite-tag clickable"
                      @click="jumpToKnowledge(point)">
                  {{ point }}
                </span>
              </div>
            </div>
            <div class="info-item">
              <span class="label">近似习题：</span>
              <div class="value tags">
                <span v-for="(exercise, index) in selectedNode.similarExercises" 
                      :key="index" 
                      class="tag similar-tag clickable"
                      @click="jumpToExercise(exercise)">
                  {{ exercise }}
                </span>
              </div>
            </div>
            <div class="actions">
              <el-button type="primary" @click="viewExerciseDetail">查看完整习题</el-button>
            </div>
          </template>
          
          <!-- 知识点详情 -->
          <template v-else-if="selectedNode.type === 'knowledge'">
            <div class="info-item">
              <span class="label">知识点名称：</span>
              <span class="value">{{ selectedNode.name }}</span>
            </div>
            <div class="info-item">
              <span class="label">相关习题：</span>
              <div class="value tags">
                <span v-for="(exercise, index) in selectedNode.relatedExercises" 
                      :key="index" 
                      class="tag exercise-tag clickable"
                      @click="jumpToExercise(exercise)">
                  {{ exercise }}
                </span>
              </div>
            </div>
          </template>
        </div>
      </div>
    </div>
    </div>
</template>

<script>
import * as echarts from 'echarts';

export default {
  name: 'ExerciseDiagram',
  data() {
    return {
      chart: null,
      drawerVisible: false,
      isExpanded: false,
      loading: false,
      selectedNode: null,
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      knowledgeTreeData: [
        {
          label: '热力学',
          children: [
            { label: '热力学第一定律' },
            { label: '热力学第二定律' }
          ]
        },
        {
          label: '动力学',
          children: [
            { label: '分子动力学' },
            { label: '牛顿运动定律' }
          ]
        }
      ],
      mockData: {
        nodes: [
          // 习题节点
          { 
            id: 'A', 
            name: '习题 A',
            type: 'exercise',
            category: 0,
            symbol: 'circle',
            description: '局部经验公式力 F，为求取最大值，分别对 x 和 y 求偏导数，并令其等于零。',
            knowledgePoints: ['热力学第一定律', '偏导数'],
            prerequisites: ['牛顿第二定律', '热力学基础'],
            similarExercises: ['习题 B', '习题 D']
          },
          { 
            id: 'B', 
            name: '习题 B',
            type: 'exercise',
            category: 1,
            symbol: 'circle',
            description: '计算分子经验公式，求解分子量。',
            knowledgePoints: ['分子动力学'],
            prerequisites: ['化学计量', '分子结构'],
            similarExercises: ['习题 A', '习题 C']
          },
          { 
            id: 'C', 
            name: '习题 C',
            type: 'exercise',
            category: 2,
            symbol: 'circle',
            description: '分析热力学系统的能量转换过程。',
            knowledgePoints: ['热力学第一定律', '热力学第二定律'],
            prerequisites: ['热力学基础'],
            similarExercises: ['习题 B', '习题 D']
          },
          { 
            id: 'D', 
            name: '习题 D',
            type: 'exercise',
            category: 0,
            symbol: 'circle',
            description: '研究理想气体的状态方程。',
            knowledgePoints: ['热力学第一定律'],
            prerequisites: ['气体定律'],
            similarExercises: ['习题 A', '习题 C']
          },
          // 知识点节点
          {
            id: 'K1',
            name: '热力学第一定律',
            type: 'knowledge',
            symbol: 'hexagon',
            category: 3,
            relatedExercises: ['习题 A', '习题 C', '习题 D']
          },
          {
            id: 'K2',
            name: '分子动力学',
            type: 'knowledge',
            symbol: 'hexagon',
            category: 3,
            relatedExercises: ['习题 B']
          },
          {
            id: 'K3',
            name: '热力学第二定律',
            type: 'knowledge',
            symbol: 'hexagon',
            category: 3,
            relatedExercises: ['习题 C']
          },
          {
            id: 'K4',
            name: '气体定律',
            type: 'knowledge',
            symbol: 'hexagon',
            category: 3,
            relatedExercises: ['习题 D']
          }
        ],
        links: [
          // 习题与知识点的关系
          {
            source: 'A',
            target: 'K1',
            value: '所属知识点',
            lineStyle: { color: '#2196F3' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          },
          {
            source: 'B',
            target: 'K2',
            value: '所属知识点',
            lineStyle: { color: '#2196F3' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          },
          {
            source: 'C',
            target: 'K1',
            value: '所属知识点',
            lineStyle: { color: '#2196F3' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          },
          {
            source: 'C',
            target: 'K3',
            value: '所属知识点',
            lineStyle: { color: '#2196F3' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          },
          {
            source: 'D',
            target: 'K1',
            value: '所属知识点',
            lineStyle: { color: '#2196F3' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          },
          {
            source: 'K4',
            target: 'D',
            value: '前序知识点',
            lineStyle: { color: '#4CAF50' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          },
          // 习题之间的关系
          {
            source: 'B',
            target: 'A',
            value: '相似习题',
            lineStyle: { color: '#FF9800' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          },
          {
            source: 'C',
            target: 'B',
            value: '相似习题',
            lineStyle: { color: '#FF9800' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          },
          {
            source: 'D',
            target: 'A',
            value: '相似习题',
            lineStyle: { color: '#FF9800' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          },
          {
            source: 'D',
            target: 'C',
            value: '相似习题',
            lineStyle: { color: '#FF9800' },
            symbol: ['none', 'arrow'],
            label: { show: true }
          }
        ]
      },
      searchQuery: '',
      originalNodes: [], // 用于存储原始节点数据
      originalLinks: [], // 用于存储原始连接数据
    };
  },
  computed: {
    getPanelTitle() {
      if (!this.selectedNode) return '';
      return this.selectedNode.type === 'exercise' ? '习题详情' : '知识点详情';
    },
    filteredTreeData() {
      if (!this.searchQuery) {
        return this.knowledgeTreeData;
      }
      return this.filterTree(this.knowledgeTreeData, this.searchQuery);
    }
  },
  watch: {
    searchQuery(val) {
      this.$refs.tree.filter(val);
    }
  },
  mounted() {
    this.initChart();
    window.addEventListener('resize', this.handleResize);
    document.addEventListener('click', this.handleOutsideClick);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.handleResize);
    document.removeEventListener('click', this.handleOutsideClick);
    if (this.chart) {
      this.chart.dispose();
    }
  },
  methods: {
    initChart() {
      const chartDom = this.$refs.chart;
      this.chart = echarts.init(chartDom);

      // 保存原始数据
      this.originalNodes = [...this.mockData.nodes];
      this.originalLinks = [...this.mockData.links];

      const option = {
        tooltip: {
          trigger: 'item',
          formatter: (params) => {
            if (params.dataType === 'node') {
              const type = params.data.type === 'exercise' ? '习题' : '知识点';
              return `${type}：${params.data.name}`;
            } else if (params.dataType === 'edge') {
              return `关系：${params.data.value}`;
            }
          }
        },
        legend: {
          data: ['基础习题', '进阶习题', '综合习题', '知识点'],
          textStyle: {
            color: '#000000'
          },
          selectedMode: false
        },
        series: [{
          type: 'graph',
          layout: 'force',
          draggable: true,
          roam: 'scale',
          nodeScaleRatio: 0.6,
          autoCurveness: true,
          data: this.mockData.nodes.map(node => ({
            ...node,
            category: node.type === 'knowledge' ? 3 : node.category,
            itemStyle: {
              color: node.type === 'knowledge' ? '#FF4081' : 
                     node.category === 0 ? '#1976D2' :
                     node.category === 1 ? '#4CAF50' :
                     '#FFC107'
            },
            emphasis: {
              scale: true,
              focus: 'adjacency'
            }
          })),
          links: this.mockData.links.map(link => ({
            ...link,
            lineStyle: {
              ...link.lineStyle,
              width: 2,
              curveness: 0.1,
              opacity: 1,
              color: link.lineStyle.color || '#bbb'
            },
            symbol: ['none', 'arrow'],
            symbolSize: [0, 8],
            label: {
              ...link.label,
              show: true,
              formatter: '{c}',
              fontSize: 10,
              color: '#000000'
            }
          })),
          categories: [
            { 
              name: '基础习题',
              itemStyle: {
                color: '#1976D2'
              }
            },
            { 
              name: '进阶习题',
              itemStyle: {
                color: '#4CAF50'
              }
            },
            { 
              name: '综合习题',
              itemStyle: {
                color: '#FFC107'
              }
            },
            { 
              name: '知识点',
              itemStyle: {
                color: '#FF4081'
              }
            }
          ],
          zoom: 1.2,
          center: ['50%', '50%'],
          label: {
            show: true,
            position: 'right',
            fontSize: 12,
            color: '#000000',
            distance: 5
          },
          force: {
            repulsion: 1000,
            edgeLength: 150,
            gravity: 0.2,
            layoutAnimation: true,
            friction: 0.1,
            initLayout: 'circular'
          },
          itemStyle: {
            borderColor: '#fff',
            borderWidth: 2,
            shadowColor: 'rgba(0, 0, 0, 0.2)',
            shadowBlur: 4
          },
          symbolSize: 25
        }]
      };

      this.chart.setOption(option);
      
      // 等待布局稳定后固定节点位置
      setTimeout(() => {
        const nodes = this.chart.getOption().series[0].data;
        const fixedNodes = nodes.map(node => ({
          ...node,
          fixed: true
        }));
        
        this.chart.setOption({
          series: [{
            data: fixedNodes,
            force: {
              layoutAnimation: false
            }
          }]
        });
      }, 3000);

      // 修改事件绑定方式
      this.chart.off('click');
      this.chart.on('click', (params) => {
        if (params.dataType === 'node') {
          const nodeData = this.mockData.nodes.find(node => node.id === params.data.id);
          if (nodeData) {
            this.selectedNode = { ...nodeData };
            this.drawerVisible = true;
            this.isExpanded = false;
          }
        }
      });
    },
    handleExpand() {
      this.isExpanded = true;
    },
    handleCollapse() {
      this.isExpanded = false;
    },
    handleClose() {
      this.drawerVisible = false;
      this.isExpanded = false;
      this.selectedNode = null;
    },
    handleResize() {
      if (this.chart) {
        this.chart.resize();
      }
    },
    handleOutsideClick(event) {
      if (this.drawerVisible) {
        const panel = document.querySelector('.detail-panel');
        const chart = document.querySelector('.chart');
        if (panel && !panel.contains(event.target) && (!chart || !chart.contains(event.target))) {
          this.handleClose();
        }
      }
    },
    handleTreeNodeClick(data) {
      const knowledgeNode = this.mockData.nodes.find(
        n => n.type === 'knowledge' && n.name === data.label
      );

      if (knowledgeNode) {
        // 获取当前图表的所有节点位置信息
        const currentData = this.chart.getOption().series[0].data;
        const nodePositions = {};
        currentData.forEach(node => {
          nodePositions[node.id] = {
            x: node.x,
            y: node.y,
            fixed: true
          };
        });

        // 收集相关节点和连线
        const relatedNodes = new Set();
        const relatedLinks = new Set();
        
        relatedNodes.add(knowledgeNode.id);
        
        // 找到与该知识点相关的所有习题和连线
        this.mockData.links.forEach(link => {
          if (link.source === knowledgeNode.id || link.target === knowledgeNode.id) {
            relatedNodes.add(link.source);
            relatedNodes.add(link.target);
            relatedLinks.add(JSON.stringify(link)); // 将link对象转为字符串以便比较
          }
        });

        // 更新图表，高亮相关节点和连线，同时保持节点位置
        const updatedNodes = this.mockData.nodes.map(node => ({
          ...node,
          x: nodePositions[node.id]?.x,
          y: nodePositions[node.id]?.y,
          fixed: true,
          itemStyle: {
            ...node.itemStyle,
            opacity: relatedNodes.has(node.id) ? 1 : 0.1
          },
          label: {
            show: true,
            position: 'right',
            fontSize: 12,
            color: '#000000',
            opacity: relatedNodes.has(node.id) ? 1 : 0.1
          }
        }));

        const updatedLinks = this.mockData.links.map(link => ({
          ...link,
          lineStyle: {
            ...link.lineStyle,
            opacity: relatedLinks.has(JSON.stringify(link)) ? 1 : 0.1,
            width: relatedLinks.has(JSON.stringify(link)) ? 3 : 1
          },
          label: {
            ...link.label,
            show: true,
            formatter: '{c}',
            fontSize: 10,
            color: '#000000',
            opacity: relatedLinks.has(JSON.stringify(link)) ? 1 : 0.1
          }
        }));

        // 更新图表配置
        this.chart.setOption({
          series: [{
            data: updatedNodes,
            links: updatedLinks,
            force: {
              layoutAnimation: false
            }
          }]
        });
      }
    },
    resetView() {
      // 重新初始化图表
      this.chart.clear();
      
      const option = {
        tooltip: {
          trigger: 'item',
          formatter: (params) => {
            if (params.dataType === 'node') {
              const type = params.data.type === 'exercise' ? '习题' : '知识点';
              return `${type}：${params.data.name}`;
            } else if (params.dataType === 'edge') {
              return `关系：${params.data.value}`;
            }
          }
        },
        legend: {
          data: ['基础习题', '进阶习题', '综合习题', '知识点'],
          textStyle: {
            color: '#000000'
          },
          selectedMode: false
        },
        series: [{
          type: 'graph',
          layout: 'force',
          draggable: true,
          roam: 'scale',
          nodeScaleRatio: 0.6,
          autoCurveness: true,
          data: this.mockData.nodes.map(node => ({
            ...node,
            category: node.type === 'knowledge' ? 3 : node.category,
            itemStyle: {
              color: node.type === 'knowledge' ? '#FF4081' : 
                     node.category === 0 ? '#1976D2' :
                     node.category === 1 ? '#4CAF50' :
                     '#FFC107',
              opacity: 1
            },
            emphasis: {
              scale: true,
              focus: 'adjacency'
            }
          })),
          links: this.mockData.links.map(link => ({
            ...link,
            lineStyle: {
              ...link.lineStyle,
              width: 2,
              curveness: 0.1,
              opacity: 1,
              color: link.lineStyle.color || '#bbb'
            },
            symbol: ['none', 'arrow'],
            symbolSize: [0, 8],
            label: {
              ...link.label,
              show: true,
              formatter: '{c}',
              fontSize: 10,
              color: '#000000',
              opacity: 1
            }
          })),
          categories: [
            { 
              name: '基础习题',
              itemStyle: {
                color: '#1976D2'
              }
            },
            { 
              name: '进阶习题',
              itemStyle: {
                color: '#4CAF50'
              }
            },
            { 
              name: '综合习题',
              itemStyle: {
                color: '#FFC107'
              }
            },
            { 
              name: '知识点',
              itemStyle: {
                color: '#FF4081'
              }
            }
          ],
          zoom: 1.2,
          center: ['50%', '50%'],
          label: {
            show: true,
            position: 'right',
            fontSize: 12,
            color: '#000000',
            distance: 5
          },
          force: {
            repulsion: 1000,
            edgeLength: 150,
            gravity: 0.2,
            layoutAnimation: true,
            friction: 0.1,
            initLayout: 'circular'
          },
          itemStyle: {
            borderColor: '#fff',
            borderWidth: 2,
            shadowColor: 'rgba(0, 0, 0, 0.2)',
            shadowBlur: 4
          },
          symbolSize: 25
        }]
      };

      // 使用完整配置重新初始化图表
      this.chart.setOption(option, true);

      // 等待布局稳定后固定节点位置
      setTimeout(() => {
        const nodes = this.chart.getOption().series[0].data;
        const fixedNodes = nodes.map(node => ({
          ...node,
          fixed: true
        }));
        
        this.chart.setOption({
          series: [{
            data: fixedNodes,
            force: {
              layoutAnimation: false
            }
          }]
        });
      }, 3000);
    },
    focusOnKnowledge(knowledgeName) {
      const node = this.mockData.nodes.find(
        n => n.type === 'knowledge' && n.name === knowledgeName
      );
      if (node) {
        this.chart.dispatchAction({
          type: 'focusNodeAdjacency',
          dataIndex: this.mockData.nodes.indexOf(node)
        });
      }
    },
    jumpToKnowledge(knowledgeName) {
      const node = this.mockData.nodes.find(
        n => n.type === 'knowledge' && n.name === knowledgeName
      );
      if (node) {
        this.selectedNode = node;
      }
    },
    jumpToExercise(exerciseName) {
      const node = this.mockData.nodes.find(
        n => n.type === 'exercise' && n.name === exerciseName
      );
      if (node) {
        this.selectedNode = node;
      }
    },
    viewExerciseDetail() {
      // 使用window.open在新窗口中打开习题详情页
      const routeData = this.$router.resolve({ 
        name: 'ExaminationQuestions', 
        params: { id: this.selectedNode.id } 
      });
      window.open(routeData.href, '_blank');
      this.$emit('view-detail', this.selectedNode);
    },
    handleChartClick(event) {
      event.stopPropagation();
    },
    filterNode(value, data) {
      if (!value) return true;
      return data.label.toLowerCase().includes(value.toLowerCase());
    },
    filterTree(data, query) {
      const filteredData = data.filter(item => {
        const matchesQuery = item.label.toLowerCase().includes(query.toLowerCase());
        if (item.children) {
          item.children = this.filterTree(item.children, query);
          return matchesQuery || item.children.length > 0;
        }
        return matchesQuery;
      });
      
      // 如果有搜索结果，展开所有节点
      if (query && filteredData.length > 0) {
        this.$nextTick(() => {
          this.$refs.tree.store.defaultExpandAll = true;
        });
      }
      
      return filteredData;
    },
    handleSearch(value) {
      this.$refs.tree.filter(value);
    },
    handleSearchClear() {
      this.searchQuery = '';
      this.$refs.tree.filter('');
      // 重置树的展开状态
      this.$refs.tree.store.defaultExpandAll = false;
      // 重新加载树数据
      this.$refs.tree.updateKeyChildren(null, this.knowledgeTreeData);
      // 重置图表到初始状态
      this.resetView();
    }
  }
};
</script>

<style lang="scss" scoped>
.exercise-container {
  width: 100%;
  height: 100vh;
  position: relative;
  background: #f5f6fb;
  display: flex;
  overflow: hidden;
}

.knowledge-tree {
  width: 250px;
  background: #fff;
  border-right: 1px solid #eee;
  display: flex;
  flex-direction: column;

  .tree-header {
    padding: 16px;
    border-bottom: 1px solid #eee;

    .title {
      font-size: 16px;
      font-weight: bold;
      color: #000000;
    }
  }

  .search-box {
    padding: 16px;
    border-bottom: 1px solid #eee;
  }

  :deep(.el-tree) {
    flex: 1;
    padding: 16px;
  }
}

.toolbar {
  position: absolute;
  top: 20px;
  left: 270px;
  z-index: 1;
  display: flex;
  gap: 8px;
}

.chart-container {
  flex: 1;
  height: 100%;
  position: relative;
}

.detail-panel {
  position: absolute;
  right: -420px;
  width: 400px;
  height: 850px;
  z-index: 9999;
  top: 50px;
  background-color: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(13px);
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: rgba(142, 142, 142, 0.19) 0px 6px 15px 0px;
  border-radius: 15px;
  color: rgba(255, 255, 255, 0.3);
  transition: all 0.3s ease;
  display: flex;
  flex-direction: column;
  opacity: 0;
  pointer-events: none;
  
  &.show {
    right: 10px;
    opacity: 1;
    pointer-events: auto;
  }
  
  &.expanded {
    width: 800px;
  }

  .detail-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1);

    .header-left {
      .expand-btn {
        cursor: pointer;
        color: #000000;
        font-size: 14px;
        
        &:hover {
          color: #40a9ff;
        }
      }
    }

    .header-right {
      .close-btn {
        cursor: pointer;
        color: #000000;
        font-size: 20px;
        line-height: 1;
        padding: 4px 8px;
        
        &:hover {
          color: #666;
        }
      }
    }
  }

  .detail-body {
    height: calc(100% - 56px);
    padding: 20px;
    overflow-y: auto;
    background-color: transparent;
    position: relative;

    .detail-content {
      .info-item {
        margin-bottom: 20px;

        .label {
          display: block;
          font-weight: 500;
          color: #000000;
          margin-bottom: 8px;
        }

        .value {
          color: #000000;

          &.description {
            padding: 12px;
            background: #f5f5f5;
            border-radius: 4px;
            line-height: 1.6;
          }

          &.tags {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;

            .tag {
              padding: 4px 8px;
              border-radius: 4px;
              font-size: 12px;
              color: #fff;

              &.knowledge-tag {
                background: #2196F3;
              }

              &.prerequisite-tag {
                background: #4CAF50;
              }

              &.similar-tag {
                background: #FF9800;
              }

              &.exercise-tag {
                background: #9C27B0;
              }

              &.clickable {
                cursor: pointer;
                transition: opacity 0.2s;

                &:hover {
                  opacity: 0.8;
                }
              }
            }
          }
        }
      }
    }
  }

  .actions {
    margin-top: 24px;
    text-align: center;
  }
}
</style>